package xin.qixia.common.core;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

/**
 * @author qixia
 */
public class AutoQueryWrapper<T> extends QueryWrapper<T> {

    public AutoQueryWrapper<T> eq(boolean condition, SFunction<T, ?> column, Object val) {
        super.eq(condition, toUnderline(column), val);
        return this;
    }

    public AutoQueryWrapper<T> eq(SFunction<T, ?> column, Object val) {
        super.eq(isNotEmpty(val), toUnderline(column), val);
        return this;
    }

    public AutoQueryWrapper<T> ne(boolean condition, SFunction<T, ?> column, Object val) {
        super.ne(condition, toUnderline(column), val);
        return this;
    }

    public AutoQueryWrapper<T> ne(SFunction<T, ?> column, Object val) {
        super.ne(isNotEmpty(val), toUnderline(column), val);
        return this;
    }

    public AutoQueryWrapper<T> gt(SFunction<T, ?> column, Object val) {
        super.gt(isNotEmpty(val), toUnderline(column), val);
        return this;
    }

    public AutoQueryWrapper<T> ge(SFunction<T, ?> column, Object val) {
        super.ge(isNotEmpty(val), toUnderline(column), val);
        return this;
    }

    public AutoQueryWrapper<T> lt(SFunction<T, ?> column, Object val) {
        super.lt(isNotEmpty(val), toUnderline(column), val);
        return this;
    }

    public AutoQueryWrapper<T> le(SFunction<T, ?> column, Object val) {
        super.le(isNotEmpty(val), toUnderline(column), val);
        return this;
    }

    public AutoQueryWrapper<T> like(Boolean condition, SFunction<T, ?> column, Object val) {
        super.like(condition, toUnderline(column), val);
        return this;
    }

    public AutoQueryWrapper<T> like(SFunction<T, ?> column, Object val) {
        super.like(isNotEmpty(val), toUnderline(column), val);
        return this;
    }

    public AutoQueryWrapper<T> between(SFunction<T, ?> column, Object val1, Object val2) {
        super.between(isNotEmpty(val1) && isNotEmpty(val1), toUnderline(column), val1, val2);
        return this;
    }

    public AutoQueryWrapper<T> in(SFunction<T, ?> column, Collection<?> coll) {
        super.in(isNotEmpty(coll), toUnderline(column), coll);
        return this;
    }

    public AutoQueryWrapper<T> inSql(SFunction<T, ?> column, String sql) {
        super.inSql(toUnderline(column), sql);
        return this;
    }

    public AutoQueryWrapper<T> isNotNull(SFunction<T, ?> column) {
        super.isNotNull(toUnderline(column));
        return this;
    }

    public AutoQueryWrapper<T> isNull(SFunction<T, ?> column) {
        super.isNull(toUnderline(column));
        return this;
    }

    public AutoQueryWrapper<T> singleResult() {
        super.last("limit 1");
        return this;
    }

    public AutoQueryWrapper<T> orderByAsc(SFunction<T, ?> column) {
        super.orderByAsc(toUnderline(column));
        return this;
    }

    public AutoQueryWrapper<T> orderByDesc(SFunction<T, ?> column) {
        super.orderByDesc(toUnderline(column));
        return this;
    }

    /**
     * 方法名转下划线命名
     *
     * @param str
     * @return
     */
    private String toUnderline(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        StringBuilder result = new StringBuilder();
        for (char c : str.toCharArray()) {
            if (Character.isUpperCase(c)) {
                result.append('_');
            }
            result.append(Character.toLowerCase(c));
        }
        return result.toString().replace("get_", "");
    }

    /**
     * 方法名转下划线命名
     *
     * @param column
     * @return
     */
    private <R> String toUnderline(SFunction<R, ?> column) {
        return toUnderline((LambdaUtils.extract(column).getImplMethodName()));
    }

    /**
     * 判断是否不为空
     *
     * @param obj
     * @return
     */
    private static boolean isNotEmpty(Object obj) {
        return !isEmpty(obj);
    }

    /**
     * 判断是否为空
     *
     * @param obj
     * @return
     */
    private static boolean isEmpty(Object obj) {
        if (null == obj) {
            return true;
        }

        if (obj instanceof CharSequence) {
            return ((CharSequence) obj).isEmpty();
        } else if (obj instanceof Map) {
            return ((Map<?, ?>) obj).isEmpty();
        } else if (obj instanceof Iterable) {
            return !((Iterable<?>) obj).iterator().hasNext();
        } else if (obj instanceof Iterator) {
            return !((Iterator<?>) obj).hasNext();
        } else if (obj.getClass().isArray()) {
            return 0 == Array.getLength(obj);
        }

        return false;
    }

}
